package com.uvstu.common.pay.client;

import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.uvstu.common.pay.config.AlipayConfig;
import com.uvstu.common.pay.exception.TClientException;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @version V1.0
 * @Title: 支付宝功能集成
 * @author: zhengweibin
 * @Description:
 * @create: 2022-12-02 23:01
 */
public class AliPayClient {

    /**
     * 初始化配置
     *
     * @param url             网关地址
     * @param appid           应用ID
     * @param appPrivateKey   应用私钥
     * @param alipayPublicKey 支付宝公钥
     * @param signType        签名类型
     * @param format          请求格式
     * @param charset         请求编码
     * @param notifyUrl       异步通知地址
     * @param returnUrl       同步通知地址
     */
    public static void setAliPayConfig(String url, String appid, String appPrivateKey, String alipayPublicKey,
                                       String signType, String format, String charset, String notifyUrl, String returnUrl) throws TClientException {
        new AlipayConfig(url, appid, appPrivateKey, alipayPublicKey, signType, format, charset, notifyUrl, returnUrl);
    }

    /**
     * 支付宝支付
     *
     * @param outTradeNo     平台订单号
     * @param totalAmount    总金额
     * @param subject        标题
     * @param body           描述
     * @param timeoutExpress 有效期（例如：5分钟 = 5m ）
     * @param productCode    产品代码 电脑网站支付：FAST_INSTANT_TRADE_PAY  手机网站支付：QUICK_WAP_WAY
     * @return
     * @throws TClientException
     */
    public static String pay(String outTradeNo, String totalAmount, String subject, String body, String timeoutExpress, String productCode) throws TClientException {
        //电脑网站支付：FAST_INSTANT_TRADE_PAY    手机网站支付：QUICK_WAP_WAY
        if ("FAST_INSTANT_TRADE_PAY".equals(productCode)) {
            return pcPay(outTradeNo, totalAmount, subject, body, timeoutExpress);
        } else if ("FAST_INSTANT_TRADE_PAY".equals(productCode)) {
            return wapPay(outTradeNo, totalAmount, subject, body, timeoutExpress);
        } else {
            throw new TClientException("支付宝支付失败，产品代码错误！");
        }
    }

    /**
     * PC网站支付
     *
     * @param outTradeNo     平台订单号
     * @param totalAmount    总金额
     * @param subject        标题
     * @param body           描述
     * @param timeoutExpress 有效期（例如：5分钟 = 5m ）
     * @return
     * @throws TClientException
     */
    public static String pcPay(String outTradeNo, String totalAmount, String subject, String body, String timeoutExpress) throws TClientException {
        AlipayClient alipayClient = AlipayConfig.getAlipayClient();
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no", outTradeNo);
        jsonObject.put("subject", subject);
        //电脑网站支付：FAST_INSTANT_TRADE_PAY    手机网站支付：QUICK_WAP_WAY
        jsonObject.put("product_code", "FAST_INSTANT_TRADE_PAY");
        jsonObject.put("total_amount", totalAmount);
        jsonObject.put("body", body);
        jsonObject.put("timeout_express", timeoutExpress);
        alipayRequest.setBizContent(jsonObject.toString());
        try {
            AlipayTradePagePayResponse response = alipayClient.pageExecute(alipayRequest);
            System.err.println(response.getBody());
            return response.getBody();
        } catch (AlipayApiException e) {
            throw new TClientException("支付宝支付调用失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * H5网站支付
     *
     * @param outTradeNo     平台订单号
     * @param totalAmount    总金额
     * @param subject        标题
     * @param body           描述
     * @param timeoutExpress 有效期（例如：5分钟 = 5m ）
     * @return
     * @throws TClientException
     */
    public static String wapPay(String outTradeNo, String totalAmount, String subject, String body, String timeoutExpress) throws TClientException {
        AlipayClient alipayClient = AlipayConfig.getAlipayClient();
        AlipayTradeWapPayRequest wapPayRequest = new AlipayTradeWapPayRequest();
        wapPayRequest.setReturnUrl(AlipayConfig.return_url);
        wapPayRequest.setNotifyUrl(AlipayConfig.notify_url);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no", outTradeNo);
        jsonObject.put("subject", subject);
        //电脑网站支付：FAST_INSTANT_TRADE_PAY    手机网站支付：QUICK_WAP_WAY
        jsonObject.put("product_code", "QUICK_WAP_WAY");
        jsonObject.put("total_amount", totalAmount);
        jsonObject.put("body", body);
        jsonObject.put("timeout_express", timeoutExpress);
        wapPayRequest.setBizContent(JSONObject.toJSONString(jsonObject));
        try {
            String form = (alipayClient.pageExecute((AlipayRequest) wapPayRequest)).getBody();
            System.out.println("form==>" + form);
            return form;
        } catch (AlipayApiException e) {
            throw new TClientException("支付宝支付调用失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 扫码支付
     *
     * @param outTradeNo     平台订单号
     * @param totalAmount    总金额
     * @param subject        标题
     * @return
     * @throws TClientException
     */
    public static String qrPay(String outTradeNo, String totalAmount, String subject) throws TClientException {
        AlipayClient alipayClient = AlipayConfig.getAlipayClient();
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setReturnUrl(AlipayConfig.return_url);
        request.setNotifyUrl(AlipayConfig.notify_url);
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", outTradeNo);
        bizContent.put("total_amount", totalAmount);
        bizContent.put("subject", subject);
        request.setBizContent(bizContent.toString());
        try{
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                return response.getQrCode();
            } else {
                throw new TClientException("支付宝支付第三方参数错误!");
            }
        }catch (Exception e){
            throw new TClientException("支付宝支付调用失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 支付结果处理
     *
     * @param request
     */
    public static Map<String, String> payResult(HttpServletRequest request) throws Exception {
        try {
            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = iter.next();
                String[] values = requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++)
                    valueStr = (i == values.length - 1) ? (valueStr + values[i]) : (valueStr + values[i] + ",");
                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            }
            boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, "utf-8", AlipayConfig.SIGNTYPE);
            if (signVerified) {
                return params;
            } else {
                throw new TClientException("支付宝签名验证失败！");
            }
        } catch (Exception e) {
            throw new TClientException("支付宝结果解析失败！错误信息：" + e.getMessage());
        }
    }


    /**
     * 支付查询
     *
     * @param outTradeNo 平台订单号
     * @param tradeNo    支付宝交易号
     * @return
     * @throws TClientException
     */
    public static Map<String, Object> payQuery(String outTradeNo, String tradeNo) throws TClientException {
        try {
            AlipayClient alipayClient = AlipayConfig.getAlipayClient();
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            //商户订单号
            model.setOutTradeNo(outTradeNo);
            //支付宝交易号
            model.setTradeNo(tradeNo);
            request.setBizModel(model);
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                JSONObject result = (JSONObject) JSONObject.parse(response.getBody());
                return result;
            } else {
                throw new TClientException("支付宝订单查询失败！状态码：" + response.isSuccess());
            }
        } catch (Exception e) {
            throw new TClientException("支付宝订单查询失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 退款
     *
     * @param outTradeNo   商户订单号
     * @param tradeNo      支付宝交易号
     * @param refundAmount 退款金额
     * @param refundReason 退款原因
     * @return
     * @throws TClientException
     */
    public static Map<String, Object> refund(String outTradeNo, String tradeNo, String refundAmount, String refundReason) throws TClientException {
        try {
            AlipayClient alipayClient = AlipayConfig.getAlipayClient();
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("trade_no", tradeNo);
            bizContent.put("refund_amount", refundAmount);
            bizContent.put("out_request_no", outTradeNo);
            bizContent.put("refund_reason", refundReason);
            request.setBizContent(bizContent.toString());
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                System.out.println("调用成功");
                JSONObject result = (JSONObject) JSONObject.parse(response.getBody());
                return result;
            } else {
                System.out.println("调用失败");
                throw new TClientException("支付宝订单退款失败!");
            }
        } catch (Exception e) {
            throw new TClientException("支付宝订单退款失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 退款查询
     *
     * @param outTradeNo 商户订单号
     * @param tradeNo    支付宝交易号
     * @return
     * @throws TClientException
     */
    public static Map<String, Object> refundQuery(String outTradeNo, String tradeNo) throws TClientException {
        try {
            AlipayClient alipayClient = AlipayConfig.getAlipayClient();
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
            //支付宝交易号
            model.setTradeNo(tradeNo);
            //商户订单号
            model.setOutTradeNo(outTradeNo);
            //退款请求号。 请求退款接口时，传入的退款请求号，如果在退款请求时未传入，则该值为创建交易时的商户订单号。
            model.setOutRequestNo(outTradeNo);
            request.setBizModel(model);
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
            System.out.println(response.getBody());
            if (response.isSuccess()) {
                JSONObject result = (JSONObject) JSONObject.parse(response.getBody());
                return result;
            } else {
                throw new TClientException("支付宝订单退款查询失败！");
            }
        } catch (Exception e) {
            throw new TClientException("支付宝订单退款查询失败！错误信息：" + e.getMessage());
        }
    }


}
